package br.com.mkmts.dao.jpa.cadastro;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.NoResultException;

import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import br.com.mkmts.dao.cadastro.EstoqueDao;
import br.com.mkmts.dao.jpa.JpaGenericDao;
import br.com.mkmts.dto.ProdutoDTO;
import br.com.mkmts.model.constants.TipoFluxoEstoqueEnum;
import br.com.mkmts.model.produtos.EstoqueEntity;
import br.com.mkmts.model.produtos.EstoqueHistoricoEntity;
import br.com.mkmts.model.produtos.ProdutoEntity;
import br.com.mkmts.utils.Adapter;
import br.com.mkmts.view.controller.menu.pedidos.utils.EstoqueCalcUtils;

@Repository
public class EstoqueDaoImpl extends JpaGenericDao<EstoqueEntity, Integer>
		implements EstoqueDao {

	@SuppressWarnings("unchecked")
	@Override
	public List<ProdutoDTO> findByFilter(String codMk, String nomeProduto,
			List<Integer> codCategoria, boolean estoqueFiltro) {
		
		if(!estoqueFiltro && codMk.equals("") && nomeProduto.equals("") && codCategoria.isEmpty()){
			return carregaOcorrencias(getEntityManager().createQuery(SELECT+_ESPACE+ORDER_BY, EstoqueEntity.class).getResultList());
		}
		
		boolean flag = false;
		StringBuilder query = new StringBuilder();
		
		query.append(SELECT);
		query.append(_ESPACE);
		
		if(estoqueFiltro){
			query.append("WHERE e.disponivel = 1");
			query.append(_ESPACE);
			flag = true;
		}
		
		if(!codMk.equals("")){
			if(flag){
				query.append("AND e.codProduto = "+codMk+"");
				query.append(_ESPACE);
			}else{
				query.append("WHERE e.codProduto = "+codMk+"");
				query.append(_ESPACE);
				flag = true;
			}
		}

		if(!nomeProduto.equals("")){
			if(flag){
				query.append("AND e.codProduto.descProduto LIKE '%"+nomeProduto+"%'");
				query.append(_ESPACE);
			}else{
				query.append("WHERE e.codProduto.descProduto LIKE '%"+nomeProduto+"%'");
				query.append(_ESPACE);
				flag = true;
			}
		}	
		
		if(!codCategoria.isEmpty()){
			String c = codCategoria.toString().replace("[", "").replace("]", "");
			
			if(flag){
				query.append("AND e.codProduto.codCategoria IN("+c+")");
				query.append(_ESPACE);
				
			}else{
				query.append("WHERE e.codProduto.codCategoria IN("+c+")");
				query.append(_ESPACE);
				flag = true;
			}
		}	
		
		query.append(ORDER_BY);
		
		return carregaOcorrencias((List<EstoqueEntity>) getEntityManager().createQuery(query.toString(), EstoqueEntity.class).getResultList());
	}
	
	@Override
	public ProdutoDTO findProductByCode(ProdutoDTO produto) {
		String query = SELECT+_ESPACE+"WHERE e.codProduto = "+produto.getCodProduto().getCodProduto();
		ProdutoDTO dto = new ProdutoDTO();
		try{
			EstoqueEntity returnzz = getEntityManager().createQuery(query, EstoqueEntity.class).getSingleResult();
			dto.setCodProduto(returnzz.getCodProduto());
			dto.setQuantidadeEmEstoque(returnzz.getQtdeProdutoEmEstoque());
			dto.setQtdeTotalPontosProdutoCarrinho(returnzz.getQtdeTotalPontosDoProduto());
			dto.setValorTotalProdutoCarrinho(returnzz.getValorTotalEmEstoqueDoProduto());
			
			return dto;
			
		}catch(NoResultException nre){
			return null;
		}
	}
	
	@Override
	@Transactional
	public void updateProductsStock(List<ProdutoDTO> produtos) {
		Date dtMovimentacao = new Date();
		for (int i = 0; i < produtos.size(); i++) {
			ProdutoDTO produto = produtos.get(i);
			StringBuilder builder = new StringBuilder();
			
			if(produto.isDisponivel()){
				String updateEstoque = "UPDATE EstoqueEntity e SET";
				if(produto.getQdteProdutoCarrinho() > 0 || produto.getQdteProdutoCarrinho() != null){
					produto.setQuantidadeEmEstoque(EstoqueCalcUtils.calcularQtdeDispEmEstoquePorProduto(produto));
					if(produto.getQuantidadeEmEstoque() <= 0){
						builder.append("DELETE EstoqueEntity e" );builder.append(_ESPACE);
						builder.append("WHERE e.codProduto.idProduto = :idProduto");builder.append(_ESPACE);
						getEntityManager().createQuery(builder.toString())
							.setParameter("idProduto", produto.getCodProduto().getIdProduto())
							.executeUpdate();
						produto.setDisponivel(false);
					}else{
						builder.append(updateEstoque);builder.append(_ESPACE);
						if(produto.isFluxoSaida()){
							builder.append("  e.qtdeTotalPontosDoProduto = e.qtdeTotalPontosDoProduto - :qtdeTotalPontosDoProdutoCarrinho");builder.append(_ESPACE);
							builder.append(", e.valorTotalEmEstoqueDoProduto = e.valorTotalEmEstoqueDoProduto - :valorTotalEmEstoqueDoProduto");builder.append(_ESPACE);
							builder.append(", e.qtdeProdutoEmEstoque = e.qtdeProdutoEmEstoque - :qtdeProdutoEmEstoque");builder.append(_ESPACE);
						}else{
							builder.append("  e.qtdeTotalPontosDoProduto = e.qtdeTotalPontosDoProduto + :qtdeTotalPontosDoProdutoCarrinho");builder.append(_ESPACE);
							builder.append(", e.valorTotalEmEstoqueDoProduto = e.valorTotalEmEstoqueDoProduto + :valorTotalEmEstoqueDoProduto");builder.append(_ESPACE);
							builder.append(", e.qtdeProdutoEmEstoque = e.qtdeProdutoEmEstoque + :qtdeProdutoEmEstoque");builder.append(_ESPACE);
						}
					
						produto.setQtdeTotalPontosProdutoCarrinho(EstoqueCalcUtils.calcularQtdeTotalPontosPorProduto(produto));
						produto.setValorTotalProdutoCarrinho(EstoqueCalcUtils.calcularValorTotalPorProduto(produto));
						
						builder.append("WHERE e.codProduto.idProduto = :idProduto");builder.append(_ESPACE);
						getEntityManager().createQuery(builder.toString())
						.setParameter("qtdeTotalPontosDoProdutoCarrinho", produto.getQtdeTotalPontosProdutoCarrinho())
						.setParameter("valorTotalEmEstoqueDoProduto", produto.getValorTotalProdutoCarrinho())
						.setParameter("qtdeProdutoEmEstoque", produto.getQdteProdutoCarrinho())//pego do carrinho pq na query ele soma/subtrai com o ja existente
						.setParameter("idProduto", produto.getCodProduto().getIdProduto())
						.executeUpdate();
					}
				}else{
					return;
				}
			}else{
				if(produto.getQdteProdutoCarrinho() <= 0 || produto.getQdteProdutoCarrinho() == null){
					return;
				}
				EstoqueEntity estEntity = new EstoqueEntity();
				estEntity.setCodProduto(Adapter.dtoToEntity(produto));
				estEntity.setDisponivel(Boolean.TRUE);
				estEntity.setQtdeProdutoEmEstoque(produto.getQdteProdutoCarrinho());
				estEntity.setQtdeTotalPontosDoProduto(produto.getCodProduto().getPontosPorUnidade()* produto.getQdteProdutoCarrinho());
				estEntity.setValorTotalEmEstoqueDoProduto(produto.getCodProduto().getPreco().multiply(BigDecimal.valueOf(produto.getQdteProdutoCarrinho())));
				insert(estEntity);
				produto.setDisponivel(true);
			}
			//adicionar no EstoqueHistoricoDao
			EstoqueHistoricoEntity historico = new EstoqueHistoricoEntity();
			historico.setCodProduto(produto.getCodProduto());
			historico.setTipoFluxoEstoque(produto.getTipoFluxoEstoque());
			historico.setDisponivel(produto.isDisponivel());
			historico.setDtMovimentacao(dtMovimentacao);
			historico.setQtdeEntradaProduto(produto.isFluxoSaida() == true ? 0 : produto.getQdteProdutoCarrinho());
			historico.setQtdeSaidaProduto(produto.isFluxoSaida() == true ? produto.getQdteProdutoCarrinho() : 0);
			historico.setTipoFluxoEstoque(produto.getTipoFluxoEstoque());
			historico.setValorDaMovimentacao(produto.getCodProduto().getPreco().multiply(BigDecimal.valueOf(produto.getQdteProdutoCarrinho())));
			getEntityManager().persist(historico);
		}
	}

	private List<ProdutoDTO> carregaOcorrencias(List<EstoqueEntity> listaRetornada){
		List<ProdutoDTO> dto = new ArrayList<ProdutoDTO>();
		for (int i = 0; i < listaRetornada.size(); i++) {
			ProdutoDTO obj = new ProdutoDTO();
			obj.setCodProduto(listaRetornada.get(i).getCodProduto());
			obj.setDisponivel(listaRetornada.get(i).isDisponivel());
			obj.setQtdePontosTotalProdutoEstoque(listaRetornada.get(i).getQtdeTotalPontosDoProduto());
			obj.setValorTotalProdutoEstoque(listaRetornada.get(i).getValorTotalEmEstoqueDoProduto());
			obj.setQuantidadeEmEstoque(listaRetornada.get(i).getQtdeProdutoEmEstoque());
			dto.add(obj);
		}
		return dto;
	}
	
}
